package com.wangxi.networkrequeststudy

import android.annotation.SuppressLint
import android.media.MediaPlayer
import android.os.Bundle
import android.util.Base64
import android.util.Log
import android.widget.Button
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import com.google.gson.Gson
import com.google.gson.JsonParser
import com.wangxi.util.HttpUtil
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import okhttp3.Call
import okhttp3.Callback
import okhttp3.FormBody
import okhttp3.Headers
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.RequestBody.Companion.toRequestBody
import okhttp3.Response
import java.io.BufferedInputStream
import java.io.ByteArrayInputStream
import java.io.IOException
import java.nio.ByteBuffer
import kotlin.concurrent.thread


class MainActivity : AppCompatActivity() {

    companion object {
        val TAG = "MainActivity"
    }

    private lateinit var mIsRequestSuccessful: TextView
    private lateinit var mSendGetSyncRequest: Button
    private lateinit var mSendGetAsyncRequest: Button
    private lateinit var mSendPostSyncRequest: Button
    private lateinit var mSendPostAsyncRequest: Button

    @SuppressLint("MissingInflatedId")
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        Log.d(TAG, "onCreate ")

        mIsRequestSuccessful = findViewById(R.id.is_request_successful)
        mSendGetSyncRequest = findViewById(R.id.send_get_sync_request)  //get 同步请求
        mSendGetAsyncRequest = findViewById(R.id.send_get_async_request) //get 异步请求
        mSendPostSyncRequest = findViewById(R.id.send_post_sync_request) //post 同步请求
        mSendPostAsyncRequest = findViewById(R.id.send_post_async_request) //post 异步请求

        mSendGetSyncRequest.setOnClickListener {
            Log.d(TAG, "onCreate get 同步请求")
            mIsRequestSuccessful.text = "发送get 同步请求"
            sendGetSyncRequest()
//            getSync()
        }

        mSendGetAsyncRequest.setOnClickListener {
            Log.d(TAG, "onCreate get 异步请求")
            mIsRequestSuccessful.text = "发送get 异步请求"
            getAsync()
        }

        mSendPostSyncRequest.setOnClickListener {
            Log.d(TAG, "onCreate post 同步请求")
            mIsRequestSuccessful.text = "发送post 同步请求"
            postSync()
        }

        mSendPostAsyncRequest.setOnClickListener {
            Log.d(TAG, "onCreate post 异步步请求")
            mIsRequestSuccessful.text = "发送post 异步请求"
//            postAsync()
            postAsyncWithHeader()
        }
    }

    // 笔记链接： https://blog.csdn.net/weixin_63357306/article/details/128918616
    //get同步请求  使用携程
    fun getSync() {
        runBlocking {
            launch(Dispatchers.Default) {
                try {
                    val client = OkHttpClient()
                    val request = Request.Builder()
                        .url("https://www.httpbin.org/get?a=1&b=2")
                        .build()
                    val call = client.newCall(request)
                    val response = call.execute()//execute方法会阻塞在这里，必须等到服务器响应，得到response才会执行下面的代码
                    //val response = client.newCall(request).execute()

                    val requestData = response.body?.string()
                    if (requestData != null) {
                        showResponse(requestData)
                        Log.d("getSync", requestData)
                    }
                } catch (e: Exception) {
                    e.printStackTrace()
                }

            }
        }
    }

    // get同步请求  使用线程开启子线程
    private fun sendGetSyncRequest() {
        Log.d(TAG, "thread before")
        thread {
            val client = OkHttpClient()
            val request = Request.Builder()
                .url("https://suapi.net/api/phone/getArea?phone=18982651131")   //https://www.httpbin.org/get?a=1&b=2   ,?后面传递的是参数
                .get()  //默认get请求
                .build()

            // 准备好请求的call对象
            val call = client.newCall(request)
            try {
                // 执行请求
                val response = call.execute()
                // 响应体
                val responseData = response.body?.string()

                Log.d(TAG, "responseData= $responseData")
                if (responseData != null) {
                    showResponse(responseData)

                    //
/*                    const reader = response.body.getReader();
                    while (1){
                        const{done,value} = await reader.read();
                        if (done){
                            break;
                        }
                        console.log(value);
                    }*/
                    //

//                    val jsonObject = JsonParser.parseString(responseData).asJsonObject
//                    val content = jsonObject.getAsJsonObject("data").get("content").asString
//                    val decodedBytes = Base64.decode(content, Base64.DEFAULT)
//                    val mediaPlayer = MediaPlayer()
//                    try {
//                        BufferedInputStream(ByteArrayInputStream(decodedBytes))
//                        //mediaPlayer.setDataSource(java.io.BufferedInputStream(java.io.ByteArrayInputStream(decodedBytes)))
//                        mediaPlayer.prepare()
//                        mediaPlayer.start()
//                    } catch (e: IOException) {
//                        e.printStackTrace()
//                    }
                    // parseJSONWithJSONObject(responseData)
                }
            } catch (e: IOException) {
                Log.e(TAG, "同步get请求发生异常，${e.message}")
            } finally {
                Log.d(TAG, "finally")
            }
        }
    }

//    {
//        "code": 200,
//        "msg": "请求成功,无Key调用仅供测试随时失效.",
//        "data": {
//        "areaName": "四川",
//        "areaCityName": "广安",
//        "postcode": "638000",
//        "area_code": "0826",
//        "providerName": "电信"
//    },
//        "exec_time": 0.039501,
//        "ip": "118.115.28.245"
//    }

    // 文档链接 ：  https://blog.csdn.net/fen_fen/article/details/120399923
    private fun parseJSONWithJSONObject(jsonData: String) {
        try {
            val jsonObject = JsonParser.parseString(jsonData).asJsonObject
            val dataElement = jsonObject["data"]

            val dataObject = dataElement.getAsJsonObject()
//            val areaElement = dataObject["areaName"]
//            val areaName = areaElement.asString
            val areaName = dataObject["areaName"].asString
            Log.i(TAG, "areaName = $areaName")
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }


    //get异步请求
    fun getAsync() {
        val client = OkHttpClient()
        val request = Request.Builder()
            .url("https://www.httpbin.org/get?a=1&b=2")
            .build()
        val call = client.newCall(request)
        //异步请求，enqueue方法不会阻塞后续代码的执行
        call.enqueue(object : Callback {
            //请求失败调用
            override fun onFailure(call: Call, e: IOException) {
                Log.w(TAG, "onFailure,get异步请求")
            }

            //请求结束调用（意味着与服务器的通信成功）
            override fun onResponse(call: Call, response: Response) {
                Log.d(TAG, "onResponse,get异步请求")
                //  响应码在200到299之间就是成功的。
                if (response.isSuccessful) {
                    var responseData = response.body?.string()
                    Log.d(TAG, "$responseData")
                    showResponse(responseData)
                }
            }
        })
        Log.d(TAG, "发生异步请求后，异步执行代码，无需等待其响应")
    }

    //post同步请求
    fun postSync() {
        thread {
            try {
                val client = OkHttpClient()
                val requestBody = FormBody.Builder()
                    .add("a", "1")
                    .add("b", "2")
                    .build()

                val request = Request.Builder()
                    .url("https://www.httpbin.org/post")
                    .post(requestBody)
                    .build()
                val call = client.newCall(request)
                val response = call.execute()//execute方法会阻塞在这里，必须等到服务器响应，得到response才会执行下面的代码
                val requestData = response.body?.string()
                if (requestData != null) {
                    Log.d("postSync", requestData)
                    showResponse(requestData)
                }
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }
    }

    //post异步请求
    fun postAsync() {
        val client = OkHttpClient()
        val requestBody = FormBody.Builder()
            .add("a", "1")
            .add("b", "2")
            .build()

        val request = Request.Builder()
            .url("https://www.httpbin.org/post")
            .post(requestBody)
            .build()
        val call = client.newCall(request)
        //异步请求，enqueue方法不会阻塞后续代码的执行
        call.enqueue(object : Callback {
            //请求失败调用
            override fun onFailure(call: Call, e: IOException) {

            }

            //请求结束调用（意味着与服务器的通信成功,）
            override fun onResponse(call: Call, response: Response) {
                if (response.isSuccessful) {
                    var responseData = response.body?.string()
                    Log.d(TAG, "$responseData")
                    showResponse(responseData)
                }
            }
        })
    }

    // 异步 post方法，带请求头
    fun postAsyncWithHeader() {
        //构建请求头
        val headers = Headers.Builder()
            .add("Content-Type", "application/json")
            .add("id", "23")
            .build()
        // 请求体
        val gson = Gson()
        var map = mutableMapOf<String, Any>()
        map["a"] = 1
        map["b"] = 2
        val params = gson.toJson(map)
        Log.d("MainActivity", "$params")
        val jsonMediaType = "application/json; charset=utf-8".toMediaType()
        val body = params.toRequestBody(jsonMediaType)

        HttpUtil.sendOKHttpRequest(
            "https://www.httpbin.org/post",
            headers,
            body,
            object : Callback {

                // onResponse()方法通常在请求成功并且服务器开始返回响应时被调用一次
                // 在处理音频流的过程中，你可以从Response对象中获取输入流，并在读取输入流的过程中逐步处理音频数据块，
                // 这可能会给人一种在持续处理响应的感觉，但这并不是onResponse()方法本身在不停被调用。
                override fun onResponse(call: Call, response: Response) {
                    // 得到服务器返回的具体内容
                    val responseData = response.body?.string()
                    Log.d("MainActivity", "$responseData")
                    showResponse(responseData)

                    /*                val gson = Gson()
                                    val yourDataObject = gson.fromJson(responseBody, YourResponseDataClass::class.java)
                                    // 现在可以访问解析后的对象属性
                                    println(yourDataObject.key1)
                                    println(yourDataObject.key2)

                                    val inputStream: InputStream = response.body!!.byteStream()
                                    // 这里可以逐块读取音频流数据进行处理，但不是不停调用 onResponse()
                                    val buffer = ByteArray(4096)
                                    var bytesRead: Int
                                    while ((inputStream.read(buffer).also { bytesRead = it })!= -1) {
                                        // 处理音频数据块
                                    }*/
                }

                override fun onFailure(call: Call, e: IOException) {
                    Log.d("MainActivity", "$call   ${e.message}")
                    showResponse(e.message)
                }
            })
    }

    fun decodeBase64ToBuffer(base64String: String): ByteBuffer? {
        val decodedBytes = Base64.decode(base64String, Base64.DEFAULT)
        return if (decodedBytes != null && decodedBytes.isNotEmpty()) ByteBuffer.wrap(decodedBytes) else null
    }

    fun showResponse(response: String?) {
        Log.d("MainActivity", "response=$response")
        runOnUiThread {
            // 在这里进行UI操作，将结果显示到界面上
            mIsRequestSuccessful.text = response
        }
    }
}